/* 
 * Quechua - the lightweight data mining framework
 *
 * Copyright (C) 2012 Marek Denis <quechua@octogan.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/log.h"

// static variables initialization
LOGLEVELS Logging::level = CRITIC;
bool Logging::colorize = true;
FILE* Logging::logging_stream = stdout;

Logging::~Logging() {
    if(Logging::colors) 
        os << endmarker;
    os << '\n';
    fprintf(logging_stream, "%s", os.str().c_str());
    fflush(logging_stream);
}

std::ostringstream& Logging::output(const char* filename, u_int32_t line,
                                  LOGLEVELS level_) {
    if(level_ <= level ) {  
        current_level = level_;
        static char buf[64];
        time_t rawtime;
        struct tm timeinfo;
        time(&rawtime);
        localtime_r ( &rawtime, &timeinfo );
        memset(buf,0,64);
        snprintf(buf,64,"[%02d %02d %04d %02d:%02d:%02d]",
                    timeinfo.tm_mday, timeinfo.tm_mon + 1, 
                    timeinfo.tm_year + 1900, timeinfo.tm_hour, 
                    timeinfo.tm_min, timeinfo.tm_sec);
        if(Logging::colorize) 
            os << colors[level_][0]; 
        os << "- " << buf ;
        os << " "
           << colors[level_][1] << " "
           << strip(filename) << ":" << line << '\t';
    }
    return os;
}

std::ostringstream& Logging::raw_output(LOGLEVELS level_) {
    os << colors[level_][0];
    return os;
}

const char* Logging::strip(const char* filename) {
    size_t len = strlen(filename);
    size_t i;
    for(i=len;i>0;--i) {
        if(filename[i] == '/')
            return filename + (++i);
    }
    return filename;
}


/* Terminal Colors
 * Attribute codes:
 * 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
 * Text color codes:
 * 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
 * Background color codes:
 * 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white 
*/
 const char* const Logging::colors[8][2] ={
                                           {"",           "DISABLED"},
                                           {"\033[37;1m", "INFO"}, 
                                           {"\033[32;1m", "MESSAGE"},
                                           {"\033[35;1m", "WARN"},
                                           {"\033[31;1m", "ERROR"},
                                           {"\033[31;1m", "CRITIC"},
                                           {"\033[36;1m", "DEBUG"},
                                           {"\033[36;1m", "VERBOSE"}
                                          };  
 
 const char* const Logging::endmarker = "\033[0m";

LOGLEVELS logname2level(const char* logname) {
   if(!strncmp(logname,"INFO",4))
       return INFO;
   if(!strncmp(logname,"MESSAGE",7))
       return MESSAGE;
   if(!strncmp(logname,"WARN",4))
       return WARN;
   if(!strncmp(logname,"ERROR",5))
       return ERROR;
    if(!strncmp(logname,"CRITIC",6))
       return CRITIC;
   if(!strncmp(logname,"DEBUG",5))
       return DEBUG;
   if(!strncmp(logname,"VERBOSE",7))
       return VERBOSE;
   
   return DISABLED;
}

LOGLEVELS Logging::get_level() {
    return Logging::level;
};

void Logging::set_level(LOGLEVELS level_) {
    Logging::level =level_;
};

FILE*& Logging::get_stream() {
    return Logging::logging_stream;
};

void Logging::redirect_output(const char* path) {
    if(Logging::logging_stream == stdout || Logging::logging_stream == stderr) {
        FILE* fh = fopen(path,"a+");
        if(!fh) {
            LOG(ERROR) << "Cannot open log file " << path
                       << ". Disabling ALL logging activity.";
            level = DISABLED;
            return;
        }
        logging_stream = fh;
        Logging::colorize = false; // turn off coloring
    }
};

void Logging::close_output() {
    if(logging_stream!=stdout && logging_stream!=stderr) {
        if(fclose(logging_stream)) {
            fprintf(stdout,"Error closing log file\n");
            fflush(stdout);
        }
    }
};

void Logging::setcolorize(bool c) {
    colorize = c;
};

bool Logging::getcolorize() {
    return colorize;
}

